package com.sc.socket.chatroom.server;

import com.sc.socket.common.CloseUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author shuc001
 * @Date 2019-02-06 23:36
 */
public  class ClientHandler{

    private final Socket client;
    private final ClientReadHandler clientReadHandler;
    private final ClientWriteHandler clientWriteHandler;
    private final ClientHandlerCallback callback;
    private final String clientInfo;
    public ClientHandler(Socket client,ClientHandlerCallback callback) throws IOException {
        this.client = client;
        this.callback = callback;
        this.clientReadHandler = new ClientReadHandler(client.getInputStream());
        this.clientWriteHandler = new ClientWriteHandler(client.getOutputStream());
        this.clientInfo = "A["+client.getInetAddress()+"]"+"P["+client.getPort()+"]";
        System.out.println(clientInfo);
    }


    public void send(String str) {
        clientWriteHandler.send(str);
    }

    public void exit0() {
        clientReadHandler.exit();
        clientWriteHandler.exit();
        CloseUtils.close(client);
        System.out.println("退出");
    }

    private void exitBySelf() {
        exit0();
        callback.onSelfClose(this);
    }





    public void readToPrint() {
        clientReadHandler.start();
    }

    class ClientWriteHandler{
        private final PrintStream printStream;
        private boolean done = false;
        private final ExecutorService executorService;
        ClientWriteHandler(OutputStream outputStream) {
            this.printStream = new PrintStream(outputStream);
            this.executorService = Executors.newSingleThreadExecutor();
        }

        public void send(String str) {

            if(done){
                return;
            }
            executorService.submit(new WriteRunnable(str));
        }

        class WriteRunnable implements Runnable{
            private final String msg;

            WriteRunnable(String msg) {
                this.msg = msg;
            }

            @Override
            public void run() {
                ClientWriteHandler.this.printStream.println(msg);
            }
        }

        void exit(){
            done=true;
            CloseUtils.close(printStream);
            executorService.shutdownNow();
        }
    }

    class ClientReadHandler extends Thread{
        private boolean done = false;
        private final InputStream inputStream;

        ClientReadHandler(InputStream inputStream) {
            this.inputStream = inputStream;
            System.out.println("新连接读取线程: "+client.getInetAddress()+" "+client.getPort());
        }

        @Override
        public void run() {
            try{
                BufferedReader input = new BufferedReader(new InputStreamReader(inputStream));
                do{
                    String str = input.readLine();
                    if(str==null){
                        System.out.println("空字符串");
                        ClientHandler.this.exitBySelf();
                        break;
                    }
                    callback.onNewMsgArrived(ClientHandler.this,str);
                }while (!done);
                input.close();
            }catch (Exception e){
                if(!done){
                    System.out.println("客户端异常退出");
                    ClientHandler.this.exitBySelf();
                }
            }finally {
                CloseUtils.close(inputStream);
            }
        }

        void exit(){
            done=true;
            CloseUtils.close(inputStream);
        }
    }

    public String getClientInfo() {
        return clientInfo;
    }
}
